#ifndef AST_CONDITIONAL
#define AST_CONDITIONAL
#include <string>
#include "node.h"

namespace AST {

    /**
     * Bloco Condicional
     *
     * Produção que executa um bloco condicional, trabalhando sobre o resultado
     * de uma expressão e executando tarefa relacionada. Armazenada como nó de
     * árvore abstrata de sintaxe, recebe como parâmetros durante sua construção
     * a expressão relacionada com a condicional e dois comandos representantes
     * de verdadeiro e falso.
     *
     * @category AST
     * @package  AST
     */
    class Conditional : public Node {

    private:

        /**
         * Expressão Condicional
         */
        Node* _expression;

        /**
         * Execução com Resultado de Sucesso
         */
        Node* _then;

        /**
         * Execução com Resultado de Falha
         */
        Node* _else;

        /**
         * Expressão Condicional
         *
         * Configura o nó de árvore abstrata de sintaxe utilizado para verificar
         * a expressão condicional do bloco. Recebe como parâmetro um nó
         * genérico de árvore, porém durante as produções da gramática, somente
         * serão apresentadas expressões.
         *
         * @param  Node* Elemento para Configuração
         * @return Próprio Objeto para Encadeamento
         */
        Conditional* _setExpression(Node*);

        /**
         * Configura Resultado de Sucesso
         *
         * Bloco de comandos utilizado para ser executado quando a expressão
         * relacionada com o bloco condicional estiver em sucesso. Recebe como
         * parâmetro um comando ou um bloco de comandos.
         *
         * @param  Node* Elemento para Configuração
         * @return Próprio Objeto para Encadeamento
         */
        Conditional* _setThen(Node*);

        /**
         * Configura Resultado de Falha
         *
         * Bloco de comandos utilizado para ser executado quando a expressão
         * relacionada com o bloco condicional estiver em falha. Recebe como
         * parâmetro um comandos ou um bloco de comandos.
         *
         * @param  Node* Elemento para Configuração
         * @return Próprio Objeto para Encadeamento
         */
        Conditional* _setElse(Node*);

    public:

        /**
         * Construtor
         *
         * Estrutura que inicializa o bloco condicional, recebendo como
         * parâmetros a expressão condicional e seus blocos de sucesso e de
         * falha; estes últimos poderão ser um único comando ou um bloco de
         * comandos, formando um novo escopo de execução.
         *
         * @param  Node* Expressão Condicional
         * @param  Node* Resultado de Sucesso
         * @param  Node* Resultado de Falha
         */
        Conditional(Node*, Node*, Node*);

        /**
         * Construtor Simplificado
         *
         * Inicialização de objeto sem o bloco condicional para falhas geradas
         * na expressão, possibilitando assim a produção sem este pedaço de
         * código.
         *
         * @param  Node* Expressão Condicional
         * @param  Node* Resultado de Sucesso
         */
        Conditional(Node*, Node*);

        /**
         * Apresenta a Expressão Condicional
         *
         * Expressão utilizada para verificar o bloco condicional relacionado,
         * resultando um teste em sucesso ou em falham que possibilita a escolha
         * de um dos blocos relacionados.
         *
         * @return Elemento Solicitado
         */
        Node* getExpression();

        /**
         * Apresenta o Bloco para Resultado em Sucesso
         *
         * Comando ou bloco de comandos que é executado sempre que a expressão
         * condicional do teste estiver em caso de sucesso. Este elemento é
         * apresentado em tempo de construção do nó de árvore abstrata de
         * sintaxe.
         *
         * @return Elemento Solicitado
         */
        Node* getThen();

        /**
         * Apresenta o Bloco para Resultado em Falha
         *
         * Comando ou bloco de comandos que é executado sempre que a expressão
         * condicional do teste estiver em caso de falha. Este elemento é
         * apresentado em tempo de construção do nó de árvore abstrata de
         * sintaxe.
         *
         * @return Elemento Solicitado
         */
        Node* getElse();

        // Sobrescrita
        std::string toString(int);

    };

};

#endif

